package model

import (
	"bytes"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"image"
	"image/gif"
	"image/jpeg"
	"image/png"
	"io"
	"os"
	"path"
	"strings"

	"github.com/chai2010/webp"
	imgtype "github.com/shamsher31/goimgtype"
)

type File struct {
	Data        io.Reader    `json:"-"`           // 读取的数据
	Image       image.Image  `json:"-"`           // 解码的数据
	Buf         bytes.Buffer `json:"-"`           // 编码的数据
	FilePath    string       `json:"filePath"`    // 选择时的全路径
	Location    string       `json:"location"`    // 文件的原位置
	Ext         string       `json:"-"`           // 扩展名
	ID          string       `json:"id"`          // id md5 计算
	MimeType    string       `json:"mimeType"`    // 文件类型
	NameOnly    string       `json:"nameOnly"`    // 文件名
	Size        int64        `json:"size"`        // 大小
	OutMimeType string       `json:"outMimeType"` // 保存的文件类型
	OutDir      string       `json:"outDir"`      // 保存的文件位置
}

type Config struct {
	OutDir     string `json:"outDir"`
	OutDirType string `json:"outDirType"` //  0 原文件夹 1 自定义
	Prefix     string `json:"prefix"`
	Suffix     string `json:"suffix"`
}

// 文件解码
func (f *File) Decode() (err error) {
	fileData, err := os.Open(f.FilePath)
	if err != nil {
		return err
	}
	defer fileData.Close()
	switch f.MimeType {
	case "jpg":
		f.Image, err = jpeg.Decode(fileData)
	case "png":
		f.Image, err = png.Decode(fileData)
	case "webp":
		f.Image, err = webp.Decode(fileData)
	case "gif":
		f.Image, err = gif.Decode(fileData)
	}
	return err
}

// 文件编码
func (f *File) Encode() (err error) {
	if f.OutMimeType == "" {
		return fmt.Errorf("没有获取到文件格式")
	}
	switch f.OutMimeType {
	case "jpg":
		jpeg.Encode(&f.Buf, f.Image, nil)
	case "png":
		png.Encode(&f.Buf, f.Image)
	case "webp":
		webp.Encode(&f.Buf, f.Image, nil)
	case "gif":
		gif.Encode(&f.Buf, f.Image, nil)
	}
	return err
}

// 获取文件信息
func (f *File) GetFileInfo() error {
	// 文件类型
	datatype, err := imgtype.Get(f.FilePath)
	if err != nil {
		f.MimeType = "unknown"
		return fmt.Errorf(" %v 不是图片文件", f.FilePath)
	}
	switch datatype {
	case `image/jpeg`, "image/jpg", "image/.jpg":
		f.MimeType = "jpg"
	case `image/png`:
		f.MimeType = "png"
	case `image/webp`:
		f.MimeType = "webp"
	case "image/gif":
		f.MimeType = "gif"
	default:
		return fmt.Errorf("该图片类型 %v 暂不能处理", datatype)
	}

	// 打开文件
	fo, err := os.Open(f.FilePath)
	if err != nil {
		return err
	}
	defer fo.Close()

	// 获取文件属性
	fs, err := fo.Stat()
	if err != nil {
		fmt.Println(err)
		return err
	}
	ext := path.Ext(f.FilePath)
	// 文件名 带后缀
	nameWithExt := fs.Name()
	f.Size = fs.Size()
	// 文件名 不带后缀
	f.NameOnly = strings.TrimSuffix(nameWithExt, ext)
	f.Ext = ext
	f.Location = strings.TrimSuffix(f.FilePath, nameWithExt)

	// 计算md5
	md5Ctx := md5.New()
	md5Ctx.Write([]byte(f.FilePath))
	f.ID = hex.EncodeToString(md5Ctx.Sum(nil))
	return nil
}
